<template>
  <el-card :body-style="{ minHeight: '350px' }">
    <el-input
      v-show="filterable"
      v-model="filterName"
      :placeholder="filterPlaceholder"
      clearable
      @input="handleInput"
    >
      <i slot="prefix" class="el-input__icon el-icon-search"></i>
    </el-input>
    <div class="transfer-title">
      <el-checkbox
        class="transfer-title-check"
        :indeterminate="isIndeterminate"
        :disabled="!data.length"
        v-model="checkAll"
        @change="handleCheckAllChange"
        >{{ checkAllTitle }}</el-checkbox
      >
      <span class="check-num">
        {{ checkList.length + "/" + checkData.length }}</span
      >
    </div>
    <main>
      <el-checkbox-group v-model="checkList" @change="handleCheckChange">
        <div
          class="transfer-checkbox-item"
          v-for="item in checkData"
          :key="item[props.key]"
        >
          <el-checkbox
            class="transfer-checkbox"
            :disabled="item[props.disabled]"
            :label="item[props.label]"
          >
          </el-checkbox>
        </div>
        <div class="empty" v-show="!checkData.length">
          {{ beSearched ? "无匹配数据" : "暂无数据" }}
        </div>
      </el-checkbox-group>
    </main>
    <footer>
      <slot name="footer">
        <el-button
          class="footer-button"
          v-for="item in buttonList"
          :key="item.key"
          :disabled="!checkList.length"
          :type="item.type"
          @click="handleConfirm(item.key)"
          >{{ item.title }}</el-button
        >
      </slot>
    </footer>
  </el-card>
</template>

<script>
export default {
  name: "transfer-view",
  props: {
    data: {
      type: Array,
      default: () => [],
    },
    // 可自定义传入的数据结构
    props: {
      type: Object,
      default: () => {
        return { key: "label_name", label: "label_name", disabled: "disabled" };
      },
    },
    filterPlaceholder: {
      type: String,
      default: "请输入搜索名称",
    },
    checkAllTitle: {
      type: String,
      default: "列表名称",
    },
    // 实际对应 列表类型 每个列表一个特有的类型与按钮关联
    buttonType: {
      type: String,
      default: "origin",
    },
    // 按钮Map对象 自定义插槽按钮可不传
    buttonMap: {
      type: Object,
      default: () => {},
    },
    // 是否可搜索
    filterable: {
      type: Boolean,
      default: true,
    },
    // 定义自己的搜索逻辑 同el
    filterMethod: {
      type: Function,
    },
  },
  data() {
    return {
      filterName: "",
      checkList: [],
      checkAll: false,
      isIndeterminate: false,
      beSearched: false,
      searchList: [],
    };
  },
  computed: {
    buttonList() {
      return this.buttonMap[this.buttonType];
    },
    checkData() {
      return this.beSearched ? this.searchList : this.data;
    },
  },
  methods: {
    /**
     * 搜索框搜索
     */
    handleInput(value) {
      if (value === "") {
        this.beSearched = false;
        return;
      }
      this.beSearched = true;
      let label = this.props.label;
      let data = this.data;
      this.searchList = data.filter((item) => {
        if (typeof this.filterMethod === "function") {
          return this.filterMethod(this.filterName, item);
        }
        return item[label].includes(value);
      });
    },
    /**
     * 全选
     */
    handleCheckAllChange(flag) {
      if (flag) {
        let label = this.props.label;
        this.checkList = this.data.map((i) => i[label]);
        this.checkAll = true;
      } else {
        this.checkList = [];
        this.checkAll = false;
      }
      this.isIndeterminate = false;
    },
    /**
     * 单选
     */
    handleCheckChange(value) {
      let length = value.length;
      this.checkAll = length === this.data.length;
      this.isIndeterminate = length > 0 && length < this.data.length;
    },
    /**
     * 按钮点击
     */
    handleConfirm(key) {
      let checkList = this.checkList;
      let label = this.props.label;
      let data = this.data.filter((item) => checkList.includes(item[label]));
      let newData = this.data.filter(
        (item) => !checkList.includes(item[label])
      );
      this.$emit("confirm", { key, data });
      this.$emit("update:data", newData);
      if (this.filterable) {
        this.resetSearchData();
      }
      this.resetData();
    },
    /**
     * 重置为原始状态
     */
    resetData() {
      this.checkAll = false;
      this.isIndeterminate = false;
      this.checkList = [];
    },
    /**
     * 重置搜索状态
     */
    resetSearchData() {
      if (this.searchList.length) {
        let label = this.props.label;
        let checkList = this.checkList;
        let searchList = this.searchList;
        this.searchList = searchList.filter(
          (i) => !checkList.includes(i[label])
        );
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.transfer-title {
  background: #f2f6fc;
  width: 100%;
  height: 50px;
  padding: 16px;
  box-sizing: border-box;
  margin-top: 12px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  .transfer-title-check {
    display: flex;
  }
  .check-num {
    color: #909399;
    font-size: 12px;
  }
}

main {
  height: 250px;
  overflow-y: auto;
  position: relative;
  border-bottom: 1px solid #e4e7ed;
  .transfer-checkbox-item {
    .transfer-checkbox {
      width: 100%;
      box-sizing: border-box;
      padding: 12px;
      display: flex;
      justify-content: flex-start;
      align-items: center;
      border-top: 1px solid #e4e7ed;
    }
    &:nth-child(1) {
      .transfer-checkbox {
        border: none;
      }
    }
  }

  .empty {
    width: 100%;
    height: 20px;
    text-align: center;

    color: #ccc;
    font-size: 13px;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 2;
  }
}
footer {
  .footer-button {
    margin-top: 12px;
  }
}
</style>
